<template>
	<view>
    <view class="function-box" v-show="!connectedDevice.deviceId">
      <view>搜索设备</view>
      <!--为了解决switch不能动态绑定checked数值，所以加一层view，然后更新时通过view的重新渲染进而渲染switch-->
      <view class="switch-box" v-if="searchSwitch.showSwitch">
        <switch :checked="searchSwitch.checked" color="#DC2115" @change="switchChange" />
      </view>
      <view class="switch-box" v-else></view>
    </view>
<!--    <divider v-if="!connectedDevice.deviceId"></divider>-->
    <view v-if="connectedDevice.deviceId">
      <section-title line-color="#DC2115" title="已配对的设备"></section-title>
      <uni-list>
        <uni-list-item
          :title="connectedDevice.name"
          rightText="取消配对"
          rightColor="#DC2115"
          icon="/static/image/connect/device.png"
          @click="modalShow"/>
      </uni-list>
    </view>
    <divider v-if="searchSwitch.checked"></divider>
    <view v-if="searchSwitch.checked">
      <section-title line-color="#DC2115" title="搜索到的可用设备"></section-title>
      <uni-list>
        <uni-list-item
          v-for="(item, index) in deviceList" :key="index"
          :title="item.name"
          rightText="配对"
          rightColor="#DC2115"
          icon="/static/image/connect/device.png"
          @click="connectDevice(item.name, item.deviceId)"/>
      </uni-list>
    </view>
		<tab-bar ref='commentTabbat' :actives="1"></tab-bar>
    <modal v-model="showModalForDisconnect" confirm-style="color: #DC2115" title='询问'
           text='是否要断开连接' @confirm='disconnectDevice'></modal>
    <modal v-model="showModalForConnect" confirm-style="color: #DC2115" title='询问'
           :text='connectModalText' @confirm='doConnectDevice'></modal>
    <message ref="message"></message>
  </view>
</template>

<script>
	import tabBar from '../../components/tabbar.vue'
  import uniList from '@/components/uni/uni-list.vue'
  import uniListItem from '@/components/uni/uni-list-item.vue'
  import divider from "../../components/divider";
	import sectionTitle from "@/components/section-title.vue"

  import store from '../../store/index.js'
  import {checkDataFromBlueTooth, dealWithDataFromBlueTooth} from "../../js/interaction";

  export default {
		data() {
			return {
        platform: '',
        deviceId: null,
        serviceId: null,
        characteristicId: null,
        searchSwitch: {
          showSwitch: true,
          checked: false,
        },
        connectModalText: '', // 连接设备的弹窗上显示的文字信息
        deviceList: [],
        connectedDevice: {
          name: '',
          deviceId: '',
          serviceId: '',
          characteristicId: ''
        },
        showModalForDisconnect: false,
        showModalForConnect: false,
        tmp: {
          name: '',
          deviceId: ''
        },
        errorDataCount: 0 // 接收数据时错误的次数，5次后停止传输
			}
		},
    onLoad() {
      this.platform = uni.getSystemInfoSync().platform;
      // TODO 开发时没有和蓝牙设备对接，所以接收不到数据，在这里用定时器来模拟
      // setInterval(() => {
      //   this.assignData();
      // }, 1000)

    },
    onShow() {
      this.connectedDevice = store.state.blueTooth.connectedDevice;
    },
		methods: {
      /**
       * 初始化蓝牙
       */
      async doInitBlueTooth(callback) {
        let result;
        try {
          result = await this.initBlueTooth();
          callback && callback()
        } catch (err) {
          result = err
        }
        return result;
      },
      initBlueTooth() {
        return new Promise((resolve, reject) => {
          uni.openBluetoothAdapter({
            success: e => {
              console.log('初始化蓝牙成功');
              resolve(true);
            },
            fail: e => {
              console.log('初始化蓝牙失败，错误码：' + (e.errCode || e.errMsg));
              reject(false)
            }
          });
        })
      },
      /**
       * 点击开关时触发的方法
       */
      async switchChange(e) {
        let value = e.target.value
        this.$set(this.searchSwitch, 'checked', value)
        // 开启的情况，要判断蓝牙开关是否打开，如果没有打开要提示用户打开
        if (value) {
          let result = await this.doInitBlueTooth();
          // 失败的话取消switch的选择状态
          if (!result) {
            this.$refs.message.info("请打开蓝牙");
            this.setSwitchCheckedFalse();
            return;
          }
          // 开始搜索设备
          this.search();
        } else {
          // 关闭的情况，停止搜索
          this.stop();
        }
      },
      /**
       * 搜索设备
       */
      search() {
        this.deviceList = []
        setTimeout(() => {
          console.log("开始搜寻智能设备");
          uni.startBluetoothDevicesDiscovery({
            success: res => {
              this.periphery();
            },
            fail: res => {
              this.$refs.message.error('查找设备失败')
            }
          });
        }, 300);
      },
      /**
       * 监听寻找新设备
       */
      periphery() {
        uni.onBluetoothDeviceFound(devices => {
          console.log('开始监听寻找到新设备的事件');
          this.get();
        });
      },
      /**
       * 获取可供连接的蓝牙设备，并过滤掉name属性为空的设备
       */
      get() {
        console.log("获取蓝牙设备");
        uni.getBluetoothDevices({
          success: res => {
            console.log('获取蓝牙设备成功:' + res.errMsg);
            this.deviceList = res.devices.filter(item => item.name && item.deviceId !== this.connectedDevice.deviceId);
          }
        });
      },
      /**
       * 打开连接设备的弹窗
       * @param name 设备名称
       * @param deviceId 设备id
       */
      connectDevice(name, deviceId) {
        this.showModalForConnect = true;
        this.tmp.name = name;
        this.tmp.deviceId = deviceId;
        this.connectModalText = `是否要连接${name}？`
      },
      /**
       * 连接设备
       */
      doConnectDevice() {
        uni.showLoading({
          title: "连接中，请稍后",
          mask: true
        })

        // 兜底关闭loading
        setTimeout(() => {
          uni.hideLoading();
        }, 10000)

        // if (name.indexOf("HC-06")) {
        //   uni.showToast({
        //     title: '设备选择有误\r\n请重新选择',
        //     icon: 'none',
        //     duration: 2000
        //   });
        //   return;
        // }
        uni.createBLEConnection({
          // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
          deviceId: this.tmp.deviceId,
          success: res => {
            setTimeout(() => {
              this.getService(this.tmp.name, this.tmp.deviceId);
            }, 1500)
          }
        });
        this.stop();
      },
      /**
       * 根据设备id获取服务id
       * @param name 设备名称
       * @param deviceId 设备id
       */
      getService(name, deviceId) {
        uni.getBLEDeviceServices({
          // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
          deviceId,
          success: res => {
            console.log(`已连接了deviceId为${deviceId}的设备`);
            if (res.services) {
              if (res.services.length !== 0) {
                if (this.platform === 'android') {
                  this.getChar(name, deviceId, res.services[3].uuid);
                } else if (this.platform === 'ios') {
                  this.getChar(name, deviceId, res.services[1].uuid);
                } else {
                  // TODO 其他设备，暂时应该不会有
                }
              } else {
                this.$refs.message.error("连接开小差了，请重试");
                uni.hideLoading();
                // 手动关闭蓝牙搜索
                this.setSwitchCheckedFalse()
                uni.closeBLEConnection({
                  deviceId,
                  success: res => {
                    store.commit('clearConnectedDevice');
                    console.log(`已断开设备id为${deviceId}设备的连接`);
                    uni.closeBluetoothAdapter({
                      success: res1 => {
                        console.log(res1)
                      }
                    })
                  }
                });
              }

              // for (let i = 0; i < res.services.length; i++) {
              // 	if (res.services[i].uuid.indexOf('FFE0') > -1) {
              // 		self.getChar(deviceId, res.services[i].uuid);
              // 		break;
              // 	}
              // }
            }
          }
        })
      },
      /**
       * 让switch开关手动关闭
       */
      setSwitchCheckedFalse() {
        this.$set(this.searchSwitch, 'showSwitch', false);
        this.$set(this.searchSwitch, 'checked', false);
        this.$nextTick(() => {
          setTimeout(() => {
            this.$set(this.searchSwitch, 'showSwitch', true);
            this.$forceUpdate() //强制更新
          },100)
        });
      },
      /**
       * 获取特征码
       * @param name 设备名称
       * @param deviceId 设备id
       * @param serviceId 服务id
       */
      getChar(name, deviceId, serviceId) {
        uni.getBLEDeviceCharacteristics({
          // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
          deviceId,
          // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
          serviceId,
          success: res => {
            let items = res.characteristics;
            if (items) {
              for (let i = 0; i < items.length; i++) {
                let item = items[i];
                if (item.properties.write) {
                  this.connectedDevice.deviceId = deviceId;
                  this.connectedDevice.name = name;
                  this.connectedDevice.serviceId = serviceId;
                  this.connectedDevice.characteristicId = item.uuid;
                }
                if (item.properties.notify) {
                  uni.notifyBLECharacteristicValueChange({
                    state: true, // 启用 notify 功能
                    // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
                    deviceId,
                    // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
                    serviceId,
                    // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
                    characteristicId: item.uuid,
                    success: res => {
                      console.log('uni.notifyBLECharacteristicValueChange - res : ', JSON.stringify(res));
                      uni.hideLoading();

                      this.$refs.message.success('连接成功')

                      // 开启数据监听
                      uni.onBLECharacteristicValueChange(res => {
                        // console.log(res);
                        console.log('uni.onBLECharacteristicValueChange');
                        // console.log("特征值改变："+JSON.stringify(res));
                        console.log(`characteristic ${res.characteristicId} has changed, now is ${JSON.stringify(res.value)}`)
                        let value = this.ab2hex(res.value);
                        console.log("ArrayBuffer转16进度字符串完成：" + value)
                        uni.setStorageSync('value', value)
                        // 处理数据
                        this.assignData(value);
                      });
                      store.commit('setConnectedDevice', {
                        'deviceId': this.connectedDevice.deviceId,
                        'serviceId': this.connectedDevice.serviceId,
                        'characteristicId': this.connectedDevice.characteristicId,
                        'name': this.connectedDevice.name
                      })
                    }
                  })
                }
              }

              // 将设备从deviceList中剔除
              this.deviceList = this.deviceList.filter(item => item.deviceId !== this.connectedDevice.deviceId);
              // 关闭设备扫描
              this.$set(this.searchSwitch, 'showSwitch', false);
              this.$set(this.searchSwitch, 'checked', false);
              this.$nextTick(() => {
                setTimeout(() => {
                  this.$set(this.searchSwitch, 'showSwitch', true);
                  this.$forceUpdate() //强制更新
                },100)
              });
            }
          }
        });
      },
      /**
       * 将蓝牙获取的数据转为十六进制
       */
      ab2hex(buffer) {
        const hexArr = Array.prototype.map.call(
          new Uint8Array(buffer),
          function(bit) {
            return ('00' + bit.toString(16)).slice(-2)
          }
        )
        return hexArr.join('')
      },
      /**
       * 接收并处理数据
       */
      assignData(data) {
        // TODO 测试数据
        // data = "02 03 08 01 F4 00 46 71 AF 51 3A F1 C1 ";
        // 校验数据
        let result = checkDataFromBlueTooth(data);
        if (!result) {
          this.errorDataCount++;
          if (this.errorDataCount >= 5) {
            this.$refs.message.error("读到的数据错误，本次读取失败，蓝牙已关闭")
            this.disconnectDevice();
            store.commit('stopAllTimer');
          }
          return;
        }
        this.errorDataCount = 0;
        dealWithDataFromBlueTooth(data);
        setTimeout(() => {
          store.commit('setReadRecordDataFalse')
          store.commit('incrementReadIndex');
          // console.log(`读取单条记录的某一次数据完毕`)
        }, 300)
      },
      /**
       * 停止搜索设备
       */
      stop() {
        uni.stopBluetoothDevicesDiscovery({
          success: res => {
            console.log('停止搜索蓝牙设备:' + res.errMsg);
          },
          fail: res => {
            console.log('停止搜索蓝牙设备失败，错误码：' + res.errCode);
          }
        });
      },
      /**
       * 提示用户是否需要断开连接
       */
      modalShow() {
        this.showModalForDisconnect = true;
      },
      /**
       * 断开连接的设备
       */
      disconnectDevice() {
        store.commit('disconnectDevice');
        this.connectedDevice = {
          name: '',
          deviceId: '',
          serviceId: '',
          characteristicId: ''
        }
      }
		},
		components: {
			tabBar, uniList, uniListItem, divider, sectionTitle
		},
    onReady() {
      this.$refs.message.setMessageToStore(this.$refs.message)
    }
	}
</script>

<style scoped lang="scss">
  @import "~@//static/css/connect.scss";
</style>

<style>
  page {
    background-color: #f5f5f5;
  }
</style>
